/* syscallLibP.h - System Call Infrastructure library private header */

/* Copyright 1984-2004 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01n,07apr05,scm  correct syscall macros for ARM/XScale...
01m,11jun04,dcc  modified SYSCALL_USER_* macros to use
                 sizeof(SYSCALL_ENTRY_STATE).
01l,15apr04,yvp  Added SYSCALL_USER_XXX_GET macros.
01k,29dec03,jeg  added simsolaris support
01j,03dec03,jb	 Adding syscall and RTP support for i86
01i,18nov03,yvp  Added typedefs for syscall hook functions.
01h,05nov03,jmp  Added include for SIMNT & SIMLINUX.
01g,15oct03,scm  add ARM link...
01f,26sep03,h_k  Added include for SH specific header.
01e,24sep03,pes  Correct conditional test for MIPS
01d,22sep03,yvp  Uncommented #include for syscall.h.
01d,19sep03,pes  Add #include for syscallMips.h
01c,15sep03,yvp  Added includes for arch-specific headers.
                 Added prototype for syscallDispatch().
01b,03sep03,yvp  Added extern for syscallGroupTbl.
01a,26aug03,yvp	 written.
*/

#ifndef __INCsyscallLibPh
#define __INCsyscallLibPh

#ifdef __cplusplus
extern "C" {
#endif

/* includes */

#include "vxWorks.h"
#include "syscallLib.h"
#include "syscall.h"

/* defines */

#define MAX_VALUE(N)	(1 << (N))	 /* Highest number represented by a 
					    bit-field N bits wide */

#define RA_MASK(N)	(MAX_VALUE(N)-1) /* Mask for a right-aligned 
					    bit-field N bits wide */

#define SYSCALL_GROUPS_MAX		MAX_VALUE(SYSCALL_GROUP_NUM_BITS)
#define SYSCALL_ROUTINES_MAX		MAX_VALUE(SYSCALL_ROUTINE_NUM_BITS)

    /* derived bit-field constants and shift counts */

#define SYSCALL_ROUTINE_NO_BIT_END	(SYSCALL_ROUTINE_NUM_BITS - 1)

#define SYSCALL_GROUP_NO_BIT_END	(SYSCALL_GROUP_NO_BIT_START + \
					 SYSCALL_GROUP_NUM_BITS - 1)

#define SYSCALL_ROUTINE_FIELD_MASK	RA_MASK(SYSCALL_ROUTINE_NUM_BITS)

#define SYSCALL_GROUP_FIELD_MASK	(RA_MASK(SYSCALL_GROUP_NUM_BITS) << \
					 SYSCALL_GROUP_NO_BIT_START)

#ifndef _ASMLANGUAGE

/* typedefs */

/* a group table entry */

typedef struct syscall_group_entry	
    {
    SYSCALL_RTN_TBL_ENTRY *	pRoutineTbl;
    int				numRoutines;
    } SYSCALL_GROUP_ENTRY;

/* externals */

extern SYSCALL_GROUP_ENTRY syscallGroupTbl [];

#endif	/* _ASMLANGUAGE */

/* Include the architecture-specific definition for SYSCALL_ENTRY_STATE */

#if     (CPU_FAMILY==PPC)
#include "arch/ppc/syscallPpc.h"
#elif	(CPU_FAMILY==ARM)
#include "arch/arm/syscallArm.h"
#elif	(CPU_FAMILY==MIPS)
#include "arch/mips/syscallMips.h"
#elif	(CPU_FAMILY==SH)
#include "arch/sh/syscallSh.h"
#elif   (CPU_FAMILY==SIMNT)
#include "arch/simnt/syscallSimnt.h"
#elif   (CPU_FAMILY==SIMLINUX)
#include "arch/simlinux/syscallSimlinux.h"
#elif   (CPU_FAMILY==SIMSPARCSOLARIS)
#include "arch/simsolaris/syscallSimsolaris.h"
#elif   (CPU_FAMILY==I80X86)
#include "arch/i86/syscallI86.h"
#else
    /*
     * - TEMPORARY -
     * A temporary definition for the SYSCALL_ENTRY_STATE structure is 
     * provided here purely as a means of avoiding compiler errors for
     * other architectures. Whenever other architectures are implemented
     * they must define a SYSCALL_ENTRY_STATE structure for themselves
     * similar to the PPC version above.
     */

typedef struct syscall_entry_state
    {
    int    args[8];             /* argument list */
    int    scn;			/* System Call Number (SCN) */
    int  * pUStack;		/* user-mode stack pointer */
    void * pc;			/* Trap return address */
    } SYSCALL_ENTRY_STATE;
#endif  /* PPC */

#ifndef _ASMLANGUAGE

#if     (CPU_FAMILY==ARM)
#define ARM_RTP_STACK_OFFSET     12  /* ARM pushes r2, SCn, and lr onto */ 
                                     /* stack prior to signal handling */
#define SYSCALL_USER_SP_GET(tid) (char *) \
	(((SYSCALL_ENTRY_STATE *) ((((WIND_TCB *)(tid))->pExcStackBase) - \
		   (sizeof(SYSCALL_ENTRY_STATE)+ARM_RTP_STACK_OFFSET)))->pUStack)

#define SYSCALL_USER_PC_GET(tid) (void *) \
	(((SYSCALL_ENTRY_STATE *) ((((WIND_TCB *)(tid))->pExcStackBase) - \
		   (sizeof(SYSCALL_ENTRY_STATE)+ARM_RTP_STACK_OFFSET)))->pc)

#define SYSCALL_USER_SCN_GET(tid) (int) \
	(((SYSCALL_ENTRY_STATE *) ((((WIND_TCB *)(tid))->pExcStackBase) - \
		   (sizeof(SYSCALL_ENTRY_STATE)+ARM_RTP_STACK_OFFSET)))->scn)
#else
#define SYSCALL_USER_SP_GET(tid) (char *) \
	(((SYSCALL_ENTRY_STATE *) ((((WIND_TCB *)(tid))->pExcStackBase) - \
				   sizeof(SYSCALL_ENTRY_STATE)))->pUStack)

#define SYSCALL_USER_PC_GET(tid) (void *) \
	(((SYSCALL_ENTRY_STATE *) ((((WIND_TCB *)(tid))->pExcStackBase) - \
				   sizeof(SYSCALL_ENTRY_STATE)))->pc)

#define SYSCALL_USER_SCN_GET(tid) (int) \
	(((SYSCALL_ENTRY_STATE *) ((((WIND_TCB *)(tid))->pExcStackBase) - \
				   sizeof(SYSCALL_ENTRY_STATE)))->scn)
#endif

/* typedefs */

typedef STATUS (* SYSCALL_ENTRY_HOOK) (const SYSCALL_ENTRY_STATE *);

typedef void   (* SYSCALL_EXIT_HOOK)  (int);

typedef STATUS (* SYSCALL_REGISTER_HOOK) (int, char *, int, 
					  SYSCALL_RTN_TBL_ENTRY **);

extern int			syscallHookTblSize;
extern SYSCALL_ENTRY_HOOK * 	pSyscallEntryHookTbl;
extern SYSCALL_EXIT_HOOK *	pSyscallExitHookTbl;
extern SYSCALL_REGISTER_HOOK *	pSyscallRegisterHookTbl;

/* function declarations */

STATUS syscallDispatch (SYSCALL_ENTRY_STATE *);
void   syscallHookLibInit (void);
STATUS syscallRegisterHookAdd (SYSCALL_REGISTER_HOOK, BOOL);
STATUS syscallRegisterHookDelete (SYSCALL_REGISTER_HOOK);
STATUS syscallEntryHookAdd (SYSCALL_ENTRY_HOOK, BOOL);
STATUS syscallEntryHookDelete (SYSCALL_ENTRY_HOOK);
STATUS syscallExitHookAdd (SYSCALL_EXIT_HOOK, BOOL);
STATUS syscallExitHookDelete (SYSCALL_EXIT_HOOK);
#endif	/* _ASMLANGUAGE */

#ifdef __cplusplus
}
#endif

#endif /* __INCsyscallLibPh */
